package hk.cic.demointegrationapp;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.CountDownTimer;

//import android.media.AudioManager;
//import android.media.SoundPool;
//import android.content.Context;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;

import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

import com.cily.utils.log.L;

import java.util.Timer;
import java.util.TimerTask;
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.StringBuffer;
//import java.util.HashMap;
import hk.cic.cwrs.bio.integration.IBioTemplateService;
import hk.cic.cwrs.bio.integration.log.IBioService;
import hk.cic.cwrs.driver.CICdevice;


/**
 * Created by raymondsung on 7/7/2015.
 */


public class BiometricDeviceService extends Service {
    private static boolean bCICDevice = false;
    private boolean flagWait = false;
    private byte revBuf[] = new byte[10];
    private int intReceive = 0;
    private int cntTry = 0;
    private boolean flagSuccess = false;
    private boolean flagFail = false;
    private boolean flagUnknown = false;
    private boolean flagBussy = false;
    //--------------------------------
    //   private int comStatus = 0;
    private int closeStatus = 0;
    private int openStatus = 0;
    private int revStatus = 0;

    //-------------------------------
    static {
        try {
                System.loadLibrary("iinterface");
                App.getApp().showToast("正準備載入生物識別APP");
                bCICDevice = true;
        } catch (Exception e) {
            App.getApp().showToast("Cannot Load iinterface.so - Probably non-CIC Device");
            L.e("BiometricDeviceService", "Cannot Load iinterface.so - Probably non-CIC Device");
        }

    }

    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return mBinder;
    }

    Runnable receiveThread = new Runnable() {
        //int revStatus = 0;
        public void run() {
            try {
                while (cntTry < 30) {

                    for (int i = 0; i < 10; i++)
                        revBuf[i] = 0;
                    intReceive = 0;
                   Thread.sleep(50);
                    intReceive = CICdevice.ReceiveRS232(revBuf);
                    if (revBuf[0] == 'S') {
                        revStatus = 1;
                        flagWait = true;
                        flagSuccess = true;
                        break;
                    } else if (revBuf[0] == 'F') {
                        revStatus = 0;
                        flagWait = true;
                        flagFail = true;
                        break;
                    } else if (cntTry == 29) {
                        revStatus = -1;
                        flagWait = true;
                        flagUnknown = true;
                        break;
                    }
                    cntTry++;
                }
                if (flagSuccess == true) {
                    flagSuccess = false;
                    cntTry = 0;
                } else if (flagFail == true) {
                    flagFail = false;
                    cntTry = 0;
                } else if (flagUnknown == true) {
                    flagUnknown = false;
                    cntTry = 0;
                }

                Message message = serviceHandler.obtainMessage();
                message.what = 1;
                serviceHandler.sendMessage(message);

            } catch (Exception e) {
                L.printException(e);
            }
        }
    };

    private void send_wiegand(long MachineID) {
        L.e("BiometricDeviceService", "MachineID:" + Long.toString(MachineID));
        long bitcheck = 0;
        String p1 = "", p2 = "";
        for (int i = 0; i < 16; i++) {
            p1 = ((MachineID & 0x00010000) != 0 ? "1" : "0") + p1;
            p2 = ((MachineID & 0x00000001) != 0 ? "1" : "0") + p2;
            bitcheck ^= MachineID;
            MachineID = (MachineID >> 1) & 0x7FFF7FFF;
        }
        String strWiegand = ((bitcheck & 0x10000) != 0 ? "1" : "0") + p1 + p2 + ((bitcheck & 0x1) != 0 ? "0" : "1");
//        String strWiegand = "0111111110001000110111001011100001";

        L.e("BiometricDeviceService", "Wiegand String:" + strWiegand);
        if (!bCICDevice)
            L.e("BiometricDeviceService", "sendWiegand() Non CIC Device - Wiegand signal not sent");
        else {
            CICdevice.SendWiegand(strWiegand);
            L.e("BiometricDeviceService", "sendWiegand() CIC Device -Wiegand signal sent");
        }
    }

    private int checkStatus() {
        if (closeStatus == -1) {
            return -1;
        } else if (openStatus == -1) {
            return -1;
        } else if (revStatus == 0) {
            return 0;
        } else if (revStatus == 1) {
            return 1;
        } else if (revStatus == -1) {
            return -1;
        } else {
            return -2;
        }
    }

    private void serial_port() {
        //---------
        byte[] sendBuf = new byte[10];
        int cntTry = 0;
        int intClose = 0;
        int intOpen = 0;
        int intSent = 0;
        for (int i = 0; i < 10; i++)
            sendBuf[i] = 0;
        flagBussy = true;

        do {
            try {
                intClose = CICdevice.CloseRS232();
                cntTry++;
                if (cntTry == 3) {
                    cntTry = 0;
                    closeStatus = -1;
                    break;
                }
            } catch (Exception e) {
                L.printException(e);
            }
        } while (intClose != 0);
        do {
            try {
                intOpen = CICdevice.OpenRS232(0);
                cntTry++;
                if (cntTry == 3) {
                    cntTry = 0;
                    openStatus = -1;
                    break;
                }
            } catch (Exception e) {
                L.printException(e);
            }
        } while (intOpen != 0);
//------
        serviceHandler.postDelayed(receiveThread, 0);
    }
    //-----------------------------

    private Handler serviceHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int msgId = msg.what;
            switch (msgId) {
                case 1:

                    break;
                default:
                    break;
            }

        }
    };

    private final IBioTemplateService.Stub mBinder = new IBioTemplateService.Stub() {
        @Override
        public String RequestTemplate(String sessionId) throws RemoteException {
            return "";
        }

        @Override
        public int SetTemplateMode(int templateMode) throws RemoteException {
            return 1;
        }


        @Override
        public String VerifyTemplate(String sessionId, String CWRNo, String template, String writeDate, String writerId, String serialNo, String greenCardExpire) throws RemoteException {

            if (flagBussy == true) {
                return "";
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
            String logmsg = sdf2.format(new java.util.Date()) + " sessionId:" + sessionId + ", CWRNo:" + CWRNo + ", template:" + template + ", writeDate:" + writeDate + ", writeId:" + writerId + ", SerialNo:" + serialNo + ", greenCardExpire: " + greenCardExpire;
            long id = 0xF0F05A5A;
            if (CWRNo.trim() != null) {
                if (CWRNo.startsWith("CWR")) {
                    id = Long.parseLong(CWRNo.substring(3));
                }
                send_wiegand(id);
            } else {
                StringBuffer sb = new StringBuffer();
                String str = "0123456789ABCDEF";
                String[] charToBin = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
                int intCheck0 = 0;
                int intCheck33 = 0;
                String strCheck0 = null;
                String strCheck33 = null;

                char chSingle6 = serialNo.charAt(6);
                int in6 = str.indexOf((int) chSingle6);
                String strBin6 = charToBin[in6];
                sb.append(strBin6);

                char chSingle7 = serialNo.charAt(7);
                int in7 = str.indexOf((int) chSingle7);
                String strBin7 = charToBin[in7];
                sb.append(strBin7);

                char chSingle4 = serialNo.charAt(4);
                int in4 = str.indexOf((int) chSingle4);
                String strBin4 = charToBin[in4];
                sb.append(strBin4);

                char chSingle5 = serialNo.charAt(5);
                int in5 = str.indexOf((int) chSingle5);
                String strBin5 = charToBin[in5];
                sb.append(strBin5);


                char chSingle2 = serialNo.charAt(2);
                int in2 = str.indexOf((int) chSingle2);
                String strBin2 = charToBin[in2];
                sb.append(strBin2);

                char chSingle3 = serialNo.charAt(3);
                int in3 = str.indexOf((int) chSingle3);
                String strBin3 = charToBin[in3];
                sb.append(strBin3);


                char chSingle0 = serialNo.charAt(0);
                int in0 = str.indexOf((int) chSingle0);
                String strBin0 = charToBin[in0];
                sb.append(strBin0);

                char chSingle1 = serialNo.charAt(1);
                int in1 = str.indexOf((int) chSingle1);
                String strBin1 = charToBin[in1];
                sb.append(strBin1);

                String strBit32 = sb.toString();

                for (int i = 0; i < 16; i++) {
                    char chBit0 = strBit32.charAt(i);
                    if (chBit0 == '1') {
                        intCheck0 ^= 1;
                    }
                }


                for (int i = 0; i < 16; i++) {
                    char chBit33 = strBit32.charAt(i + 16);
                    if (chBit33 == '1') {
                        intCheck33 ^= 1;
                    }
                }

                if (intCheck0 == 1) {
                    intCheck0 = 1;
                } else {
                    intCheck0 = 0;
                }
                strCheck0 = Integer.toString(intCheck0);

                if (intCheck33 == 1) {
                    intCheck33 = 0;
                } else {
                    intCheck33 = 1;
                }
                strCheck33 = Integer.toString(intCheck33);


                String strBit34 = strCheck0 + sb.toString() + strCheck33;
                CICdevice.SendWiegand(strBit34);

            }

            if (flagBussy == false) {
                serial_port();

                while (!flagWait) ;

                int intStatus = checkStatus();
                String strReturn = "{\"SessionID\":\"" + sessionId + "\", \"CWRNo\": \"" + CWRNo + "\", \"Result\":\"" + intStatus + "\", \"Datetime\": \"" + sdf.format(new java.util.Date()) + "\"}";
                Intent intent = new Intent("ResultLog");
                intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.putExtra("resultLog", strReturn);
                sendBroadcast(intent);
                flagWait = false;
                flagBussy = false;
//---------------------------------
                return strReturn;

            } else {
                int Error = -1;
                String strReturn = "{\"SessionID\":\"" + sessionId + "\", \"CWRNo\": \"" + CWRNo + "\", \"Result\":\"" + Error + "\", \"Datetime\": \"" + sdf.format(new java.util.Date()) + "\"}";
                return strReturn;
            }
        }
    };
}

